package name.huzhenbo.java.generics;

import java.util.HashMap;
import java.util.Map;

/**
 * The most common use of generics is for collections, such as Set and Map, and sin-
 * gle-element containers, such as ThreadLocal and AtomicReference. In all of
 * these uses, it is the container that is parameterized. This limits you to a fixed num-
 * ber of type parameters per container. Normally that is exactly what you want. A
 * Set has a single type parameter, representing its element type; a Map has two, rep-
 * resenting its key and value types; and so forth.
 *
 * Sometimes, however, you need more flexibility. For example, a database row
 * can have arbitrarily many columns, and it would be nice to be able to access all of
 * them in a typesafe manner. Luckily, there is an easy way to achieve this effect. The
 * idea is to parameterize the key instead of the container. Then present the parame-
 * terized key to the container to insert or retrieve a value. The generic type system is
 * used to guarantee that the type of the value agrees with its key.
 */
class Favorites {
    private Map<Class<?>, Object> favorites = new HashMap<Class<?>, Object>();

    public <T> void putFavorite(Class<T> type, T object) {
        if (type == null)
            throw new NullPointerException("Type is null");
        favorites.put(type, object);
    }

    public <T> T getFavorite(Class<T> type) {
        // dynamic cast
        return type.cast(favorites.get(type));
    }
}
